/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 *
 */

/**
 * ohmurl相关方法
 *
 * @since 2024/04/19
 */
import path from 'path';
import { PkgContextInfoOpt } from '@ohos/hvigor-arkts-compose';
import fse from 'fs-extra';
import { Dependency } from '../project/dependency/core/dependency-interface.js';
import { DependencyManager } from '../project/dependency/dependency-manager.js';
import { TargetTaskService } from '../tasks/service/target-task-service.js';
import { OhosLogger } from './log/ohos-logger.js';

const log: OhosLogger = OhosLogger.getLogger('ohmurl-utils');
/**
 * @normalized:<isSO>&<module name>&<bundle name>&<标准import路径>&<version>
 *
 * @param pkgInfo 信息表中收集的信息
 */
export function generateOhmUrl(pkgInfo: PkgContextInfoOpt) {
  return (
    `@normalized:${pkgInfo.isSO ? 'Y' : 'N'}&${pkgInfo.moduleName}&${pkgInfo.bundleName}&` +
    `${pkgInfo.entryPath ? `${pkgInfo.packageName}/${removeSuffix(pkgInfo.entryPath)}` : ''}&${pkgInfo.version}`
  );
}

/**
 * @normalized:<isSO>&<module name>&<bundle name>&<标准import路径>&<version>
 *
 * @param pkgInfo 信息表中收集的信息
 * @param sourceFile  文件路径sourceFile
 */
export function generateOhmUrlForSourceFile(pkgInfo: PkgContextInfoOpt, sourceFile: string): string {
  return (
    `@normalized:${pkgInfo.isSO ? 'Y' : 'N'}&${pkgInfo.moduleName}&${pkgInfo.bundleName}&` +
    `${sourceFile ? `${pkgInfo.packageName}/${removeSuffix(sourceFile)}` : ''}&${pkgInfo.version}`
  );
}

/**
 * 生成旧的ohmurl，注意这个方法只生成旧的hap/hsp自己模块编译时针对自己的srcEntry的ohmurl，依赖的har模块生成规则不同，在下面的generateOhmurlForSrcEntry方法里
 * @param targetService
 * @param srcEntry
 * @param moduleName
 */
export function getOldOhmUrlForSrcEntry(targetService: TargetTaskService, srcEntry: string, moduleName: string){
  const projectModel = targetService.getModuleService().getProjectModel();
  const bundleName = targetService.getTargetData().getProduct().bundleName ?? projectModel.getDefaultBundleName();
  const srcEntryWithoutDotSep = srcEntry.replace(/^\.\//, '');
  const srcEntryWithoutSuffix = srcEntryWithoutDotSep.substring(0, srcEntryWithoutDotSep.indexOf('.'));
  return `@bundle:${bundleName}/${moduleName}/${srcEntryWithoutSuffix}`;
}

/**
 * 生成so文件的ohmurl
 *
 * @param soPkgInfo so文件pkgContextInfo
 * @param srcEntry
 */
export function generateOhmUrlForSo(soPkgInfo: PkgContextInfoOpt, srcEntry: string): string {
  return (
    `@normalized:${soPkgInfo.isSO ? 'Y' : 'N'}&${soPkgInfo.moduleName}&${soPkgInfo.bundleName}&` +
    `${srcEntry ? path.basename(srcEntry) : ''}&${soPkgInfo.version}`
  );
}

/**
 * 生成so文件的旧格式ohmurl
 * @param targetService
 * @param srcEntry
 * @param moduleName
 */
export function generateOldOhmUrlForSo(targetService: TargetTaskService, srcEntry: string, moduleName: string) {
  const projectModel = targetService.getModuleService().getProjectModel();
  const srcEntryBaseName = path.basename(srcEntry).replace(/^lib/, '');
  const bundleName = targetService.getTargetData().getProduct().bundleName ?? projectModel.getDefaultBundleName();
  return `@app:${bundleName}/${moduleName}/${removeSuffix(srcEntryBaseName)}`;
}

/**
 * 去除主入口文件的后缀
 *
 * @param packageMainName
 */
export function removeSuffix(packageMainName: string) {
  const typeExts = ['.d.ets', '.d.ts', '.d.mjs', '.d.cjs', '.d.js', '.ets', '.ts', '.mjs', '.cjs', '.js', '.so'];
  const mainName = packageMainName.split(path.sep).join('/');
  const ext: string | undefined = typeExts.find((ext) => mainName.endsWith(ext));
  return ext ? mainName.substring(0, mainName.lastIndexOf(ext)) : mainName;
}

/**
 * 生成hap/hsp收集到依赖har中的ability-srcEntry的ohmurl
 *
 * @param targetService
 * @param moduleName
 * @param dependency
 * @param originSrcEntry
 */
export function generateOhmurlForSrcEntry(targetService: TargetTaskService, moduleName: string, dependency: Dependency, originSrcEntry: string): string {
  let ohmurl, sourceFile;
  const absoluteSrcEntryPath = targetService.getAbsoluteSrcEntryPath(originSrcEntry, dependency.getDependencyRootPath());
  if (!dependency.isByteCodeHarDependency() && !fse.existsSync(absoluteSrcEntryPath)) {
    // 仅源码har校验srcEntry的绝对路径是否真实存在;字节码har在oh_modules中不存在原文件后缀,但此处不影响字节码har后续生成ohmurl
    log.debug(
      'Failed to generate the ohmurl corresponding to the srcEntry that depends on the ability module.' +
        ' The srcEntry path for obtaining the ability of the module on which the module depends is incorrect or the corresponding file does not exist.',
    );
    return '';
  }

  const projectModel = targetService.getModuleService().getProjectModel();
  if (dependency.isLocal()) {
    const moduleModelByDependency = DependencyManager.getModuleModelByDependency(dependency, projectModel!);
    if (!moduleModelByDependency) {
      log.debug(
        'Failed to generate the ohmurl corresponding to the srcEntry that depends on the ability module.' +
          ' Failed to obtain the corresponding module model through the local dependency of the module.',
      );
      return '';
    }
    sourceFile = absoluteSrcEntryPath.substring(moduleModelByDependency.getModule().getNodeDir().length + 1);
  } else {
    sourceFile = absoluteSrcEntryPath.substring(dependency.getDependencyRootPath().length + 1);
  }

  if (targetService.getBuildOption()?.strictMode?.useNormalizedOHMUrl) {
    // 新格式
    ohmurl = generateOhmUrlForSourceFile(targetService.getPkgContextInfo(dependency.getDependencyName()), sourceFile);
  } else {
    // 旧格式
    const bundleName = targetService.getTargetData().getProduct().bundleName ?? projectModel.getDefaultBundleName();
    const srcEntryWithoutDotSep = originSrcEntry.replace(/^\.\//, '');
    const srcEntryWithoutSuffix = srcEntryWithoutDotSep.substring(0, srcEntryWithoutDotSep.indexOf('.'));
    ohmurl = `@bundle:${bundleName}/${moduleName}@${dependency.getDependencyName()}/${srcEntryWithoutSuffix}`;
  }
  return ohmurl;
}

/**
 * ArkTS1.2新格式的ohmurl
 * 格式: <package name>.<file path>.<file name>
 *
 * @param pkgInfo
 * @param srcEntry
 * @param srcPrefix
 */
export function generateOhmUrlV2ForSrcEntry(pkgInfo: PkgContextInfoOpt, srcEntry: string, srcPrefix = 'src/main',isOhosTest = false): string {
  const srcEntryPath = path.normalize(srcEntry)
  const arr =  srcEntryPath.split(':');
  const sourceFile = arr[0];
  let className = '';
  if (arr.length > 1) {
    className = arr[1];
  }

  let ohmurl;
  if (isOhosTest) {
    srcPrefix = 'src/ohosTest';
  }

  if (srcEntryPath.startsWith('build')) {
    srcPrefix = '';
    ohmurl = `${pkgInfo.packageName}/${srcPrefix}/${(removeSuffix(sourceFile)).replace(/\.?\//g, '/')}`;
  } else {
    ohmurl = `${pkgInfo.packageName}/${srcPrefix}/${(removeSuffix(sourceFile)).replace(/\.?\//g, '/')}`;
  }

  return (
    `${ohmurl}${className ? `:${className}` : ''}`
  );
}
